#-*-coding:utf8-*-

"""puits ---> Ce module contient une classe qui s’appelle Puits """

#import rsa 
from time import time, sleep
from random import *
from donnees import *
from imagerie import *
from fonction import Arbre_Donne_Etat, Energie_Capteur, Energie_Agregateur, Quelle_Categorie, Comparer_Des_Decision, Voisin
from distance import *


class Puits: 

   """ Cette classe contient les méthodes __init__ () et run() """

   def __init__(self, Foret):

       """ __init__(foret) ---> cette méthode permet initialiser l'objet de type Puits """

       self.x, self.y = POSITION_PUITS 
       self.Foret = Foret
       assert 0<=self.x <= 1
       assert 0<=self.y <= 1        
       self.valeursRecues = []
       self.valeurs = []
       self.agregateurs = []
       self.dicoCapteurs = {}
       self.lesPuits = []

       if CHIFFREMENT:
           print("On doit chiffrer les données sur le réseau")
           if fichierCles == None:
               print "Création des clés de chiffrement"
               print("Taille des clés : "+str(tailleCles))
               print("Génération des clés de "+str(tailleCles)+" bits")
               self.resume.write("Taille des clés : "+str(tailleCles)+'\n')
               (self.Kp,self.Ks) = rsa.newkeys(tailleCles)
               if SAUVEGARDE_CLES:
                   fichier = raw_input("Quel nom de fichier de clé ?")
                   dd = open('data/'+fichier,'wb')
                   dump((self.Kp,self.Ks),dd)
                   dd.close()
           else:
               ee = open(fichierCles,'rb')
               (self.Kp,self.Ks) = load(ee)
               self.resume.write("Fichier des clés : " + fichierCles+'\n')
    
           print("Les Clés publiques : "+str(self.Kp))
           print("Les Clés secretes : "+str(self.Ks))
           print("Génération finie")
       if videoRealite :
           print "-> On trace ce qui se passe réellement, dans videoRealite.avi"
           Trace_Fonction(f)

       # On lance le tout
       self.BigBang = time()
        
        
    
   def Run(self):

       """ Run() ---> cette méthode permet de démarrer le travail du réseaux, il boucle TEMPS_SIMULATION fois et chaque fois boucle TEMPS_ECOUTE fois,
       Si la Topologie est égale à 1 : pour chaque boucle, tous les capteurs captent les données et les envoient à leur agrégateur, et les agrégateurs envoient les données agrégées à l’agrégateur cible (qui peut être le puits ou un autre agrégateur) et dessine la topologie.
       Si la Topologie est égale à 2 :  pour chaque boucle, tous les capteurs captent les données et les envoient à leur capteur cible, et les capteurs cibles renvoient les donnes reçus à leur capteur cible (qui peut être puits ou un autre capteur ) et dessine la topologie. Ensuite nous utilisons les Forêts aléatoires pour prendre la décision.
       Enfin nous représentons les données reçues par le puits par une graphe 3d (la position des capteurs en fonction des données envoyées)  """ 

     
       print("LE PUITS DEMARRE LE TRAVAIL")

       global heure
       
       if not SIR :

           EnergieCapteur = []
           MortCapteur = []
           MortAgregateur = []
           EnergieAgregateur = []
           CapteursDetectentPanne = []
           MemoireC = []
           Transferer = []
           MemoireA = []

           Decision_Foret = []
           Decision_Reel = []
      
           for nombre_simulation in range(NOMBRE_SIMULATION) :

               print "C'est le {}ème SIMULATION".format(nombre_simulation)

               for cc in self.dicoCapteurs.values() :
                   cc.energie = BatterieCapteurs
                   cc.mort = False
                   cc.capteursDetectentPanne = False                   
                   cc.memoire = []

               for a, aa in enumerate(self.agregateurs) :
                   aa.energie = BatterieAgregateurs 
                   aa.mort = False
                   aa.aTransferer = []
                   for i in Categ.keys() :
                       aa.memoire[i] = []

               heure = 0
               temps_simulation = 0

           
               while temps_simulation < TEMPS_SIMULATION :
           
                   for cc in self.dicoCapteurs.values() :
                       EnergieCapteur.append(cc.energie)
                       MortCapteur.append(cc.mort)
                       CapteursDetectentPanne.append(cc.capteursDetectentPanne)
                       if Topologie == 2:
                           MemoireC.append(cc.memoire)
 
                   for a, aa in enumerate(self.agregateurs) :
                       EnergieAgregateur.append(aa.energie)  
                       MortAgregateur.append(aa.mort)
                       Transferer.append(aa.aTransferer) 
                       MemoireA.append(aa.memoire)

                   h = heure

                   # L'utilisateur précise le TEMPS_SIMULATION du réseau
                   print ("Durée écoulée de simulation "+str(nombre_simulation)+" est : "+str(temps_simulation))


                   # L'utilisateur précise le TEMPS_ECOUTE du réseau
                   print "Le TEMPS_ECOUTE est  : {} ".format(TEMPS_ECOUTE)

               
                
                   ligne = {}
        
                   for temps in range(TEMPS_ECOUTE):

                       if Topologie == 1:
          
                           # Production d'infos
                           print "    -> Agrégateurs restants :", len([ag for ag in self.agregateurs if not ag.mort])
                           print("Durée écoulée : "+str(temps)+" secondes")
                  
                 
                           # Les capteurs envoient aux agrégateurs
                           for ag in self.agregateurs:
                               if not ag.mort:
                                   # Les capteurs ont leur énergie qui décroit naturellement
                                   for cap in [capt for capt in ag.capteurs if not capt.mort]:
                                       cap.energie -= coutEcouteCapteurs

                                       if cap.energie < 0:
                                           cap.mort = True
                                   

                                       else :
                                           for i in Categ.keys():
                             
                                               if cap.Categorie == i:
                                                   # Le capteur relève alors une valeur
                                                   t=time()
                                                   if cap.capteursDetectentPanne == False:
                                                       cap.valeur = eval(Categories[i]["loi"])
                                            
                                                       if eval(loiPanne) >= 1:
                                                           cap.capteursDetectentPanne = True 
                                                   else:
                                                       cap.valeur = eval(Categories[i]["loiPanne"])

                                                   # On chiffre éventuellement la donnée
                                                   if CHIFFREMENT:
                                                       cap.cr = rsa.encrypt(str(cap.valeur), cap.Kp)
                                                   else:
                                        
                                                       cap.cr = cap.valeur


                                                   # On décrémente l'énergie du capteur du coût de transmission à l'agrégateur

                                                   # indice = 1 si le capteur capter le donnée et l'envoie a l'agregateur ou capteur cible si Topologie = 2
                                                   # indice = 2 si le capteur envoie les données au capteur cible (dans cas si Topologie = 2)

                                                   cap.energie -= Energie_Capteur(capteur = cap, cible = cap.agregateur, indice = 1, temps = t) 
                                      
                                                   if cap.energie > 0:
                                                       # Si le coût de transmission est inférieur à l'énergie restante, on envoie
                                                       # effectivement la donnée à l'agrégateur
                                                       cap.agregateur.memoire[i].append(cap.cr)
                                                       cap.sir = []
                                                   else:
                                                       # Le capteur meurt s'il n'a plus d'énergie
                                                       print "   -> Mort du capteur", cap.numero, "de l'agrégateur", ag.numero
                                                       cap.mort = True  
                                               else :
                                                   pass
                   
        
                           heure += 100./individus 

                           # Les agrégateurs envoient aux agrégateurs, ou puits, si leur mémoire est saturée.            
                           for ag in self.agregateurs :
                               if not ag.mort:
                                   if ag.aTransferer != [] :
                                       # Si un agrégateur doit transférer des données, il commence par le faire
                                       # Décrémenter l’énergie et tester avant d'envoyer à l’agrégateur cible
                                       print("   -> L'agrégateur n°" + str(ag.numero) + " doit transférer : " + str(ag.aTransferer))
                            
                                       if ag.agregateurCible != self and not ag.agregateurCible.mort:

                                           # indice = 1 : si l'agregateur agreger les données apres anvoyer a l'agregateur cible
                                           # indice = 2 : si l'agregateur va envoyer les données a l'agregateur cible

                                           ag.energie -= Energie_Agregateur(agregateur = ag ,agregateurCible = ag.agregateurCible, indice = 2)
                               
                                           if ag.energie > 0:
                                               ag.agregateurCible.aTransferer.extend(ag.aTransferer)
                                               ag.aTransferer = []
                                           else:
                                               ag.mort = True 
                                       elif  ag.agregateurCible == self :
                                           # indice = 1 : si l'agregateur va envoyer les données a l'agregateur cible
                                           # indice = 2 : si l'agregateur agreger les données apres anvoyer a l'agregateur cible

                                           ag.energie -= Energie_Agregateur(agregateur = ag ,agregateurCible = ag.agregateurCible, indice = 2)
                                
                                           if ag.energie > 0:
                                               self.valeursRecues.extend(ag.aTransferer) 
                                               ag.aTransferer = []    
                                           else:
                                               ag.mort = True 

                                                    
                 

                                       # Si la mémoire de l'égrégateur est pleine, on doit transférer les données 
                                       # après agrégation

                                   # agreger les donnees de capteurs

                                   for j  in Categ.keys():
                        
                                       while len(ag.memoire[j]) >= MemoireAgregateurs and not ag.mort:
                                           print("   -> L'Agrégateur n°" + str(ag.numero) + " agrège ")
                                           somme = 0
                                           u = time()
                                           for kk in range(MemoireAgregateurs):
                                               cr = ag.memoire[j][kk]   
                                               # Les données peuvent être chiffrées : il faut les déchiffrer
                                               if CHIFFREMENT:
                                                   valeur = int(rsa.decrypt(cr, ag.Ks))
                                               else :
                                                   valeur = cr
                                               somme += valeur   
                                           # La somme obtenue par agrégation doit peut-être être chiffrée 
                                           if CHIFFREMENT:
                                               cr = rsa.encrypt(str(somme), ag.Kp)  
                                           else:
                                               cr = str(somme)  
                    
                                           # Soit on envoie directement la somme (event. chiffrée) au puits, soit
                                           # on la transfert à son agrégateur cible  
                                           if DIRECT_AGREGATEUR_PUITS:
                                               # indice = 1 : si l'agregateur agreger les données apres anvoyer a l'agregateur cible
                                               # indice = 2 : si l'agregateur va envoyer les données a l'agregateur cible

                                               ag.energie -= Energie_Agregateur(agregateur = ag ,agregateurCible = self, indice = 1, temps = u)
                                    
                                               if ag.energie > 0:
                                                   self.valeursRecues.extend([[(ag.x, ag.y, time()-self.BigBang), j, cr]])       
                                               else:
                                                   ag.mort = True 
                                           else:

                                               if ag.agregateurCible == self:

                                                   # indice = 1 : si l'agregateur agreger les données apres anvoyer a l'agregateur cible
                                                   # indice = 2 : si l'agregateur va envoyer les données a l'agregateur cible

                                                   ag.energie -= Energie_Agregateur(agregateur = ag ,agregateurCible = ag.agregateurCible, indice = 1, temps = u)
                                        
                                                   if ag.energie > 0:
                                                       self.valeursRecues.extend([[(ag.x, ag.y, time()-self.BigBang), j, cr]]) 
                                                   else:
                                                       ag.mort = True
                                               elif not ag.agregateurCible.mort: 
 
                                                   # indice = 1 : si l'agregateur agreger les données apres anvoyer a l'agregateur cible
                                                   # indice = 2 : si l'agregateur va envoyer les données a l'agregateur cible

 
                                                   ag.energie -= Energie_Agregateur(agregateur = ag ,agregateurCible = ag.agregateurCible, indice = 1, temps = u)
                                        
                                                   if ag.energie > 0:
                                                       ag.agregateurCible.aTransferer.append([(ag.x, ag.y, time()-self.BigBang), j, cr]) 
                                                   else:
                                                       ag.mort = True       
                               
                                       
                                           # Enlever de la mémoire les données agrégées  
                                           del ag.memoire[j][:MemoireAgregateurs]  
                                           

               
  
                                   else:
                                       # L'agrégateur est vivant et sa mémoire n'est pas pleine, il ne fait donc rien
                                       pass

                                   # L'énergie des agrégateurs décroît naturellement
                                   ag.energie -= coutEcouteAgregateurs
                                   if ag.energie < 0:
                                       ag.mort = True

                       
                       elif Topologie == 2:

                           print "    -> Capteurs restants :", len([c for c in self.dicoCapteurs.values() if not c.mort])
                           print("Durée écoulée : " + str(temps) + " secondes")
                                     
                           # Les capteurs envoient Capteur Cible
                           for cpt in self.dicoCapteurs.values() :
                               if not cpt.mort:
                                   # Les capteurs ont leur énergie qui décroit naturellement 
                                   cpt.energie -= coutEcouteCapteurs
                                   if cpt.energie < 0:
                                       cpt.mort = True
                          
                        
                                   else:
                                       for i in Categ.keys():
                             
                               
                                           if cpt.Categorie == i: 

                                               if cpt.memoire != [] :
                                                   # Si un capteur doit transférer des données, il commence par le faire
                                                   # Décrémenter l’énergie et tester avant d'envoyer à la Capteur cible
                                                   print("   -> Le capreur n°"+str(cpt.numero)+" doit transférer : "+str(cpt.memoire))

                                                   if cpt.capteurCible != self and not cpt.capteurCible.mort:

                                                       # indice = 1 si le capteur capter le donnée et l'envoie a l'agregateur ou capteur cible si Topologie = 2
                                                       # indice = 2 si le capteur envoie les données au capteur cible (dans cas si Topologie = 2)

                                                       cpt.energie -= Energie_Capteur(capteur = cpt, cible = cpt.capteurCible, indice = 2) 
                                            

                                                       if cpt.energie > 0:
                                                       # Tester si le capteur cible est toujours vivant avant d'envoyer les données
                                                           cpt.capteurCible.memoire.extend(cpt.memoire)
                                                           cpt.memoire = [] 
                                                       else:
                                                           cpt.mort = True

                                                   elif cpt.capteurCible == self  :
                        
                                                       # indice = 1 si le capteur capter le donnée et l'envoie a l'agregateur ou capteur cible si Topologie = 2
                                                       # indice = 2 si le capteur envoie les données au capteur cible (dans cas si Topologie = 2)
                                          
                                                       cpt.energie -= Energie_Capteur(capteur = cpt, cible = self, indice = 2) 
                                            
                                                       if cpt.energie > 0:
                                                           self.valeursRecues.extend(cpt.memoire)
                                                           cpt.memoire = [] 
                                                       else :
                                                           cpt.mort = True 
                             
                                                 
                                               if not  cpt.mort :
                                                   # Le capteur relève alors une valeur
                                                   t = time()
                                                   if cpt.capteursDetectentPanne == False:
                                                       cpt.valeur=eval(Categories[i]["loi"])
                                            
                                                       if eval(loiPanne) >= 1:
                                                           cpt.capteursDetectentPanne = True 
                                                   else:
                                                       cpt.valeur = eval(Categories[i]["loiPanne"])
                                                   # On chiffre éventuellement la donnée
                                                   if CHIFFREMENT:
                                                       cpt.cr = rsa.encrypt(str(cap.valeur), cpt.Kp)
                                                   else:     
                                                       cpt.cr = str(cpt.valeur)

                                              
                                                   # On envoie directement à son Capteur Cible
                                                   # On décrémente l'énergie du capteur du coût de transmission à son Capteur Cible
                                                   if cpt.capteurCible == self:

                                                       # indice = 1 si le capteur capter le donnée et l'envoie a l'agregateur ou capteur cible si Topologie = 2
                                                       # indice = 2 si le capteur envoie les données au capteur cible (dans cas si Topologie = 2)

                                                       cpt.energie -= Energie_Capteur(capteur = cpt, cible = self, indice = 1, temps = t)
                                       
                                                       # Si le coût de transmission est inférieur à l'énergie restante, on envoie
                                                       if cpt.energie > 0:
                                                           self.valeursRecues.extend([[(cpt.x, cpt.y, time()-self.BigBang), i, cpt.cr]]) 
                                                       else:
                                                           cpt.mort = True

                                                   elif not cpt.capteurCible.mort :

                                                       # indice = 1 si le capteur capter le donnée et l'envoie a l'agregateur ou capteur cible si Topologie = 2
                                                       # indice = 2 si le capteur envoie les données au capteur cible (dans cas si Topologie = 2) 
                                       
                                                       cpt.energie -= Energie_Capteur(capteur = cpt, cible = cpt.capteurCible, indice = 1, temps = t) 
                                        
                                                       # Si le coût de transmission est inférieur à l'énergie restante, on envoie 
                                                       if cpt.energie > 0:
                                                           cpt.capteurCible.memoire.append([(cpt.x, cpt.y, time()-self.BigBang), i, cpt.cr])
                                                       else:
                                                           cpt.mort = True
                                   
                           heure += 100./individus 
     
                       
                   if Topologie == 1:
                       Trace_Topologie_1(self, str(nombre_simulation)+"_"+str(temps_simulation).zfill(10)) 
 
                   elif Topologie == 2:
                       Trace_Topologie_2(self, str(nombre_simulation)+"_"+str(temps_simulation).zfill(10)) 
      
                   for ty in Categories.keys():
                       ligne[ty] = []  
           
                       for i in self.valeursRecues :
                           if i[1] == ty:
                               if Topologie == 1:
                                   ligne[ty].append(eval(i[2])/MemoireAgregateurs)
                               elif Topologie == 2:
                                   ligne[ty].append(eval(i[2]))
       
 
       

                   for test in ligne.keys():
                       if ligne[test] == []:
                           ligne[test].append(Categories[test]["erreurCapteur"])


                   try:

                       decision = max([(m,[Arbre_Donne_Etat(graphe, racine, ligne) for (graphe,racine) in self.Foret].count(m)) for m in range(5)], key=lambda x:x[1])

                   except:

                       print "Nous devons répéter la {}ème tour de la simulation numéro {} ".format(temps_simulation, nombre_simulation)

                       # Faire un Sleep d'une seconde dans chaque exception
                       sleep(1)

                       for c, cc in self.dicoCapteurs.items() :
                           cc.energie = EnergieCapteur[c]
                           cc.mort = MortCapteur[c]
                           cc.capteursDetectentPanne = CapteursDetectentPanne[c]
                           if Topologie == 2:
                               cc.memoire = MemoireC[c]

                       for a, aa in enumerate(self.agregateurs):
                           aa.energie = EnergieAgregateur[a]   
                           aa.mort = MortAgregateur[a]
                           aa.aTransferer = Transferer[a] 
                           aa.memoire = MemoireA[a]
                       
                       self.valeursRecues = []
                  
                       EnergieCapteur = [] 
                       MortCapteur = []
                       CapteursDetectentPanne = []
                       MemoireC = []
                       EnergieAgregateur = [] 
                       MortAgregateur = []
                       Transferer = []
                       MemoireA = []

                       heure = h

                       continue
   
              
                   EnergieCapteur = [] 
                   MortCapteur = []
                   CapteursDetectentPanne = []
                   MemoireC = []
                   EnergieAgregateur = [] 
                   MortAgregateur = []
                   Transferer = []
                   MemoireA = []

                   print "Voici la décision sur les données captées par les capteurs {} : ".format(decision)

                   if Topologie == 1:
                       Trace_Topologie_Decision_1(self, str(nombre_simulation)+"_"+str(temps_simulation), decision)
                   elif Topologie == 2:
                       Trace_Topologie_Decision_2(self, str(nombre_simulation)+"_"+str(temps_simulation), decision)     

                   # Ajoute la décision de forêt
               
                   Decision_Foret.append(decision[0])
                  

                   # Ajoute la décision réel
                   decisionreel = Quelle_Categorie(ligne)
              
                   Decision_Reel.append(decisionreel)
                   
              

                   # Le puits récupère les valeurs reçues pour traitement (déchiffrement, si besoin est)
                   while self.valeursRecues != []:
                       valeur = self.valeursRecues[0]
                       self.valeursRecues = self.valeursRecues[1:]
                       if CHIFFREMENT:
                           decr = rsa.decrypt(str(valeur), self.Ks)
                           if Topologie == 1:
                               self.valeurs.append(int(decr)//MemoireAgregateurs)
                   
                           elif Topologie == 2:
                               self.valeurs.append(int(decr))     
                       else:
                           if Topologie == 1: 
                               self.valeurs.append((valeur[0], int(eval(valeur[2])//MemoireAgregateurs)))

                           elif Topologie == 2:
                               self.valeurs.append((valeur[0], int(eval(valeur[2]))))   
        
           
                   temps_simulation += 1

          
       
               
           self.valeurs=self.valeurs[ :300]  
       
         
      
           # Production de diverses informations (il faut faire le ménage dedans)
           if len(self.valeurs) != 0:
               print("Moyenne au puits = "+str(float(sum([k[1] for k in self.valeurs]))/len(self.valeurs)))

           print("Nombre de valeurs déchiffrées par le puits : "+str(len(self.valeurs)))
      
           print('self.valeurs'+str(self.valeurs))

           if Topologie == 1:
               # On détermine le nombre de capteurs par agrégateur
               repartition = []
               for ag in self.agregateurs:
                   repartition.append((ag.numero,len(ag.capteurs)))
               print("Répartition des capteurs par agrégateur : "+str(repartition))


           print  "Decision_Foret est : " + str(Decision_Foret) + "--" + "Decision_reel est : " + str(Decision_Reel)

           print str(Comparer_Des_Decision(Decision_Reel, Decision_Foret)) + " décision égaux par rapport à " + str(TEMPS_SIMULATION*NOMBRE_SIMULATION) + " décision " 
       

       
           print "-> On trace l'évolution de la topologie, dans filmTopologie.avi"
           Film_Topologie()

           print "-> On trace deux courbe, la décision des forêts aléatoires et la décision réelle "
           Courbe(Decision_Reel, Decision_Foret)

           # On trace les films de ce qui s'est produit...
           print "-> On trace ce qui se passe au puits, dans videoPuits.avi"

           if Topologie == 1:
               Trace_Valeurs_Puits_1(self)
           elif Topologie == 2:
               Trace_Valeurs_Puits_2(self)

       
           # Fin de la simulation
           print("On stoppe tout le monde") 
       
       
       elif SIR :

           print "Tu choisie SIR model"
           sleep(1)

           global Presence_Puits
           global Nombre_Capteur_Diffuse

           Test_Presence_Puits = Presence_Puits
           Test_Nombre_Capteur_Diffuse = Nombre_Capteur_Diffuse

           Temps_Arrive_puits = {}
           Nombre_Voisin_Intrusion = {}
           Nombre_Voisin_Vie = {}

           for Presence_Puits in [10, 20, 40, 60, 80, 100] :

               print "Simulation avec {} secondes pour le puits est arrive ".format(Presence_Puits) 
               # Faire un Sleep d'une seconde dans chaque boucle
               sleep(1)
               
               for cc in self.dicoCapteurs.values() :
                   cc.energie = BatterieCapteurs
                   cc.mort = False                 
                   cc.memoire = []

               self.valeursRecues = []
  
               for i in range(NOMBRE_SIR) :
             
                   print "C'est le {}ème SIMULATION ".format(i)

                   for temps in range(Presence_Puits):

                       print "    -> Capteurs restants :", len([c for c in self.dicoCapteurs.values() if not c.mort])
                       print("Durée écoulée : " + str(temps) + " secondes")
             
                       for cpt in self.dicoCapteurs.values() :
                           if not cpt.mort:
                           # Les capteurs ont leur énergie qui décroit naturellement 
                               cpt.energie -= coutEcouteCapteurs
                               if cpt.energie < 0:
                                   cpt.mort = True
                     
                               else:
                                   # capte si il y a une intrusion ou non
                                   cpt.valeur = randint(0, 10)

                                   cpt.memoire.append(cpt.valeur)

                                   if temps == Taux_Diffusion  and cpt.memoire.count(1) != 0 :
                                       # envoie les donnees aux voisins
                                       voisin = Voisin(self, cpt)

                                       k = 0 
                                       n = 0 

                                       while n < Nombre_Capteur_Diffuse:

                                           if not voisin[k].mort :
                                               # On décrémente l'énergie du capteur du coût de transmission à leur voisin
                                               cpt.energie -= Energie_Capteur(capteur = cpt, cible = voisin[k], indice = 2)

                                               if cpt.energie > 0 :
                                    
                                                   voisin[k].memoire.extend(cpt.memoire)
                                                   n += 1
                                               else :
                                    
                                                   cpt.mort = True
                                                   break
                                        

                                           k += 1

                                           if k == len(voisin):
                                               break 

                 
                   # La puits est arrivé
                   # envoie les donnees capte par capteur au puits

                   print "La puits est arrivé"               

                   for cpt in self.dicoCapteurs.values() :

                       if not cpt.mort: 
                           # On décrémente l'énergie du capteur du coût de transmission à la puits
                           cpt.energie -= Energie_Capteur(capteur = cpt, cible = self, indice = 2)

                           if cpt.energie > 0 :
                               self.valeursRecues.extend(cpt.memoire) 
                               cpt.memoire = []    
                 
                           else :
                               cpt.mort = True

                   print " --> Capteurs restants :", len([c for c in self.dicoCapteurs.values() if not c.mort])
   

                   Trace_Topologie_2(self, str(Presence_Puits) + str(i).zfill(10))
                
               Temps_Arrive_puits[Presence_Puits] = self.valeursRecues.count(1)


           sp = []
           X = []
           Y = []

           for i, j in  Temps_Arrive_puits.items() :
               sp.append((i,j))  
  
           sp = sorted(sp)
            
           print sp

           for x,y in sp:
               X.append(x)
               Y.append(y)

           Presence_Puits = Test_Presence_Puits
           Courbe_Temps_Puits(X, Y)

         

           # On va étudier les variation de nombre de diffusion par rapport au nombre d'intrusion capter 

           for  Nombre_Capteur_Diffuse in [0, 1, 2, 3, 4, 5] :

               print "Cette simulation possède {} diffusion de chaque capteur à son voisins  ".format(Nombre_Capteur_Diffuse) 

               # Faire un Sleep d'une seconde dans chaque boucle
               sleep(1)
               
               for cc in self.dicoCapteurs.values() :
                   cc.energie = BatterieCapteurs
                   cc.mort = False                 
                   cc.memoire = []

               self.valeursRecues = []
  
               for i in range(NOMBRE_SIR) :
             
                   print "C'est le {}ème SIMULATION ".format(i)

                   for temps in range(Presence_Puits):

                       print "    -> Capteurs restants :", len([c for c in self.dicoCapteurs.values() if not c.mort])
                       print("Durée écoulée : " + str(temps) + " secondes")
                   
                       for cpt in self.dicoCapteurs.values() :
                           if not cpt.mort:
                           # Les capteurs ont leur énergie qui décroit naturellement 
                               cpt.energie -= coutEcouteCapteurs
                               if cpt.energie < 0:
                                   cpt.mort = True
                     
                               else:
                                   # capte si il y a une intrusion ou non
                                   cpt.valeur = randint(0, 10)

                                   cpt.memoire.append(cpt.valeur)

                                   if temps == Taux_Diffusion and cpt.memoire.count(1) != 0 :
                                       # envoie les donnees aux voisins
                                       voisin = Voisin(self, cpt)

                                       k = 0 
                                       n = 0 
                                      
                                       while n < Nombre_Capteur_Diffuse:

                                           if not voisin[k].mort :
                                               # On décrémente l'énergie du capteur du coût de transmission à leur voisin
                                               cpt.energie -= Energie_Capteur(capteur = cpt, cible = voisin[k], indice = 2)

                                               if cpt.energie > 0 :
                                    
                                                   voisin[k].memoire.extend(cpt.memoire)
                                                   n += 1
                                               else :
                                    
                                                   cpt.mort = True
                                                   break
                                        

                                           k += 1

                                           if k == len(voisin):
                                               break 

                 
                   # La puits est arrivé
                   # envoie les donnees capte par capteur au puits

                   print "La puits est arrivé"               

                   for cpt in self.dicoCapteurs.values() :

                       if not cpt.mort: 
                           # On décrémente l'énergie du capteur du coût de transmission à la puits
                           cpt.energie -= Energie_Capteur(capteur = cpt, cible = self, indice = 2)

                           if cpt.energie > 0 :
                               self.valeursRecues.extend(cpt.memoire) 
                               cpt.memoire = []    
                 
                           else :
                               cpt.mort = True

                   print " --> Capteurs restants :", len([c for c in self.dicoCapteurs.values() if not c.mort])
   

                   Trace_Topologie_2(self, str(Nombre_Capteur_Diffuse) + str(i).zfill(10))
                
               Nombre_Voisin_Intrusion[Nombre_Capteur_Diffuse] = self.valeursRecues.count(1)
               
           sp = []
           Z = []
           W = []

           for i, j in  Nombre_Voisin_Intrusion.items() :
               sp.append((i,j))  
  
           sp = sorted(sp)
            
           print sp

           for x,y in sp:
               Z.append(x)
               W.append(y)


           Nombre_Capteur_Diffuse = Test_Nombre_Capteur_Diffuse 
           Courbe_Voisin_Intrusion(Z, W)

           # On va étudier les variation de nombre de diffusion par rapport au durée de la vie d'une reseaux 
 
           for  Nombre_Capteur_Diffuse in [0, 1, 2, 3, 4, 5] :

               print "Cette simulation possède {} diffusion de chaque capteur à son voisins  ".format(Nombre_Capteur_Diffuse) 

               # Faire un Sleep d'une seconde dans chaque boucle
               sleep(1)
               
               for cc in self.dicoCapteurs.values() :
                   cc.energie = BatterieCapteurs
                   cc.mort = False                 
                   cc.memoire = []

               self.valeursRecues = []
               
               t = time()
               tm = 0
               while len([c for c in self.dicoCapteurs.values() if not c.mort]) != 0 :
             

                   for temps in range(Presence_Puits):

                       print "    -> Capteurs restants :", len([c for c in self.dicoCapteurs.values() if not c.mort])
                       print("Durée écoulée : " + str(temps) + " secondes")
                   
                       for cpt in self.dicoCapteurs.values() :
                           if not cpt.mort:
                           # Les capteurs ont leur énergie qui décroit naturellement 
                               cpt.energie -= coutEcouteCapteurs
                               if cpt.energie < 0:
                                   cpt.mort = True
                     
                               else:
                                   # capte si il y a une intrusion ou non
                                   cpt.valeur = randint(0, 10)

                                   cpt.memoire.append(cpt.valeur)

                                   if temps == Taux_Diffusion and cpt.memoire.count(1) != 0 :
                                       # envoie les donnees aux voisins
                                       voisin = Voisin(self, cpt)

                                       k = 0 
                                       n = 0 
                                      
                                       while n < Nombre_Capteur_Diffuse:

                                           if not voisin[k].mort :
                                               # On décrémente l'énergie du capteur du coût de transmission à leur voisin
                                               cpt.energie -= Energie_Capteur(capteur = cpt, cible = voisin[k], indice = 2)

                                               if cpt.energie > 0 :
                                    
                                                   voisin[k].memoire.extend(cpt.memoire)
                                                   n += 1
                                               else :
                                    
                                                   cpt.mort = True
                                                   break
                                        

                                           k += 1

                                           if k == len(voisin):
                                               break 

                 
                   # La puits est arrivé
                   # envoie les donnees capte par capteur au puits

                   print "La puits est arrivé"               

                   for cpt in self.dicoCapteurs.values() :

                       if not cpt.mort: 
                           # On décrémente l'énergie du capteur du coût de transmission à la puits
                           cpt.energie -= Energie_Capteur(capteur = cpt, cible = self, indice = 2)

                           if cpt.energie > 0 :
                               self.valeursRecues.extend(cpt.memoire) 
                               cpt.memoire = []    
                 
                           else :
                               cpt.mort = True

                   print " --> Capteurs restants :", len([c for c in self.dicoCapteurs.values() if not c.mort])
   

                   Trace_Topologie_2(self, str(Nombre_Capteur_Diffuse) + str(tm).zfill(10))

                   tm += 1
               Nombre_Voisin_Vie[Nombre_Capteur_Diffuse] = time() - t
               
           sp = []
           T = []
           H = []

           for i, j in  Nombre_Voisin_Vie.items() :
               sp.append((i, j))  
  
           sp = sorted(sp)
            
           print sp

           for x, y in sp:
               T.append(x)
               H.append(y)


           Nombre_Capteur_Diffuse = Test_Nombre_Capteur_Diffuse 
           Courbe_Voisin_Vie(T, H)
 
 
           
           # Fin de la simulation
           print("On stoppe tout le monde")
  
           
       
